package be.idamf.mx.rpc
{
	import flash.events.IEventDispatcher;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	import mx.rpc.Fault;
	
	[Event(name="invoke", type="mx.rpc.events.InvokeEvent")]
	[Event(name="result", type="mx.rpc.events.ResultEvent")]
	[Event(name="fault", type="mx.rpc.events.FaultEvent")]
	
	public dynamic class TapeService extends Proxy implements IRPCService
	{
		use namespace flash_proxy;
		
		////////////////////////////////////////////////////////////////////////
		
		public static var masterTape:Object;
		
		////////////////////////////////////////////////////////////////////////
		
		[Bindable]
		public var tape:Object;

		////////////////////////////////////////////////////////////////////////
		
		protected var mockService:MockService;

		////////////////////////////////////////////////////////////////////////
		
		public function TapeService(destination:String = null, tape:Object = null)
		{
			super();
			mockService = new MockService(destination, this);
			this.destination = destination;
			this.tape = tape;
		}
		
		////////////////////////////////////////////////////////////////////////
		
		private var _destination:String;
		[Bindable]
		public function get destination():String
		{
			return _destination;
		}
		public function set destination(value:String):void
		{
			_destination = mockService.destination = value;
		}

		////////////////////////////////////////////////////////////////////////
		
		public function getResult(operation:String):*
		{
			var	tape:Object = this.tape || masterTape;
			var result:Object;
			
			if (tape && _destination && tape[_destination])
				result = tape[_destination][operation];
			
			if (tape && !_destination)
			{
				for (var id:String in tape)
				{
					if (tape[id][operation])
					{
						result = tape[id][operation];
						break;
					}
				}
			}
			
			return result;
		}
		
		////////////////////////////////////////////////////////////////////////
		// Overrides
		
		override flash_proxy function callProperty(name:*, ... rest):*
		{
			var result:* = getResult(name);
			
			if (result)
			{
				return mockService.asyncResult(result);
			}
			else
			{
				var fault:Fault = new Fault("", "No matching result data found on tape.");
				return mockService.asyncFault(fault);
			}
		}
		
		////////////////////////////////////////////////////////////////////////
		// IEventDispatcher impl
		
		public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
		{
			mockService.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
		{
			mockService.removeEventListener(type, listener, useCapture);
		}
		
		public function dispatchEvent(event:Event):Boolean
		{
			return mockService.dispatchEvent(event);
		}
		
		public function hasEventListener(type:String):Boolean
		{
			return mockService.hasEventListener(type);
		}
		
		public function willTrigger(type:String):Boolean
		{
			return mockService.willTrigger(type);
		}
	}
}